####################################
# SCons build system for Pedigree
## Tyler Kennedy (AKA Linuxhq AKA TkTech)
####################################

import os
import shutil
import tempfile
Import(['env'])

tmp = env.Clone()

# Build directories
builddir = "#" + env["PEDIGREE_BUILD_BASE"]
kerneldir = "#" + env["PEDIGREE_BUILD_KERNEL"]
moduledir = "#" + env["PEDIGREE_BUILD_MODULES"]
subsysdir = "#" + env["PEDIGREE_BUILD_SUBSYS"]

# Change to then name of this module
posix_objname = subsysdir + '/posix.o'
glue_objname = builddir + '/libpedigree-glue.a'
crt0_objname = kerneldir + '/crt0.o'
libpthread_objname = builddir + '/libpthread.a'
crti_objname = kerneldir + '/crti.o'
crtn_objname = kerneldir + '/crtn.o'
libpedigree_c_objname = builddir + '/libpedigree-c.a'

libc_objname = builddir + '/libc.so'

env.Alias("crt", [crt0_objname, crti_objname, crtn_objname])
env.Alias("subsys", posix_objname)
env.Alias("subsys", glue_objname)
env.Alias("pthreads", libpthread_objname)

env.Depends(libc_objname, glue_objname)
env.Depends(libc_objname, libpedigree_c_objname)

# To include a new subdirectory just add to the list.
subdirs = [
    
]

# To include new files just add to the list, or Glob("*.cpp")
posix_files = [
    Glob("*.cc")
]

glue_files = [
    'glue.c',
    'glue-sysconf.c',
    'glue-fseek.c',
    'glue-fpurge.c',
    'glue-scandir.c',
]

crt0_files = ['crt0.c']

suffix = '-noarch'
if env['ARCH_TARGET'] == 'X86':
    suffix = '-i686'
elif env['ARCH_TARGET'] == 'X64':
    suffix = '-amd64'
elif env['ARCH_TARGET'] == 'PPC':
    suffix = '-ppc'
elif env['ARCH_TARGET'] == 'ARM':
    suffix = '-arm'

posix_files += ["sigret" + suffix + ".s"]
glue_files += ["setjmp" + suffix + ".s"]

pthread_files = ['glue-pthread.c']

# CRTI/CRTN
crti_files = ["crti" + suffix + ".s"]
crtn_files = ["crtn" + suffix + ".s"]

# To include a new directory for includes, just add it to the list
include = [
    './syscalls',
    './include',
    '#/src/modules',
    '#/src/system/include',
    '#/src/modules/system',
    '#/src/subsys/pedigree-c',
    '.'
]

# To add a library add to the list below
if 'STATIC_DRIVERS' in env['CPPDEFINES']:
    libraries = []
else:
    libraries = ['gcc']

# To add a library path add to the list below
libpaths = [
	builddir,
    env['LIBGCC']
]

####################################
SConscript([os.path.join(i, 'SConscript') for i in subdirs],exports = ['tmp'])
tmp['CPPPATH'] = [i for i in include]
tmp['LIBS'] = [i for i in libraries]
tmp['LIBPATH'] = [i for i in libpaths]
#^-- Stupid way of doing it but I plan on adding processing.

if "STATIC_DRIVERS" in env['CPPDEFINES']:
    build = tmp.Program(posix_objname,posix_files,LINKFLAGS='-nostdlib -Wl,-r -T $LSCRIPT',LSCRIPT=File("#src/modules/link_static.ld"))
else:
    build = tmp.Program(posix_objname,posix_files,LINKFLAGS='-nostdlib -Wl,-r -T $LSCRIPT',LSCRIPT=File("#src/modules/link.ld"))

# TODO: need to set -fPIC for x86, but that means we can't use %ebx for syscalls, which causes an error.
glueFlags = " -fno-exceptions "
if env['ARCH_TARGET'] in ['X64', 'ARM']:
    glueFlags += " -fPIC "

tmp_glue = tmp.Clone()
tmp_glue['CFLAGS'] = tmp_glue['CFLAGS'].replace("mcmodel=kernel", "mcmodel=small")
tmp_glue['CXXFLAGS'] = tmp_glue['CXXFLAGS'].replace("mcmodel=kernel", "mcmodel=small")
tmp_glue['CFLAGS'] += glueFlags
tmp_glue['CXXFLAGS'] += glueFlags
tmp_glue.Library(glue_objname, glue_files) # , LINKFLAGS='-r') # + glueFlags)

tmp_crt0 = tmp.Clone()

# No libraries needed for CRT0
tmp_crt0['LIBS'] = ''
tmp_crt0.Program(crt0_objname, crt0_files, LINKFLAGS='-nostdlib -r')
    
# CRTI
tmp_crti = tmp.Clone()
tmp_crti['LIBS'] = ''
tmp_crti.Program(crti_objname, crti_files, LINKFLAGS='-nostdlib -r')

# CRTN
tmp_crtn = tmp.Clone()
tmp_crtn['LIBS'] = ''
tmp_crtn.Program(crtn_objname, crtn_files, LINKFLAGS='-nostdlib -r')

# libpthread
tmp_pthread = tmp.Clone()
tmp_pthread.Library(libpthread_objname, pthread_files)

# Build libc/libm

if env['ARCH_TARGET'] == 'X86':
    libc_arch = 'i686'
elif env['ARCH_TARGET'] == 'X64':
    libc_arch = 'amd64'
elif env['ARCH_TARGET'] == 'PPC':
    libc_arch = 'ppc'
elif env['ARCH_TARGET'] == 'ARM':
    libc_arch = 'arm'

base = tmp.Dir("#")
baseLibc = tmp.File("#src/subsys/posix/newlib-" + libc_arch + "-libc.a")
baseLibm = tmp.File("#src/subsys/posix/newlib-" + libc_arch + "-libm.a")
baseInclude = tmp.Dir("#src/subsys/posix/include")

buildDir = tmp.Dir(builddir)
buildLibc = tmp.File(builddir + '/libc.so')
buildLibm = tmp.File(builddir + '/libm.so')
buildLibcA = tmp.File(builddir + '/libc.a')
buildLibmA = tmp.File(builddir + '/libm.a')
buildInclude = tmp.Dir(builddir + '/include-posix')

env.Alias("libs", [buildLibc, buildLibm])
env.Alias("crt0", "crt")

# libc will be rebuilt every time the glue files are modified, or whenever the
# base libc.a file is changed.
env.Command([buildLibc],
            [glue_objname, baseLibc],
            "@python " + base.abspath + "/scripts/buildLibc.py " + buildDir.abspath + " " + baseLibc.abspath + " " + tmp.File(glue_objname).abspath + " " + tmp.File(libpedigree_c_objname).abspath + " " + env["AR"] + " " + env["CC_NOCACHE"]
            )

# libm will only ever be rebuilt if the libm.a file changes
env.Command([buildLibm],
            [baseLibm],
            "@python " + base.abspath + "/scripts/buildLibm.py " + buildDir.abspath + " " + baseLibm.abspath + " " + env["AR"] + " " + env["CC_NOCACHE"]
            )
